<?php

namespace app\common\service;

use Symfony\Component\Mailer\Transport;
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\Address;

use Exception;

class EmailService
{
    /**
     * 单例对象
     */
    protected static $instance;

    /**
     * mailer对象
     */
    protected $mail = [];

    /**
     * message对象
     */
    protected $message = [];

    /**
     * 错误内容
     */
    protected $_error = '';

    /**
     * 默认配置
     */
    public $options = [
        'charset' => 'utf-8', // 编码格式
        'debug' => 0, // 调式模式
        'from' => '',
        'from_name' => '',
        'to' => '',
        'to_name' => '',
        'subject' => '',
        'content_type' => '',
        'body' => '',
        'cc' => '',
        'cc_name' => '',
        'bcc' => '',
        'bcc_name' => '',
        'attach_path' => '',
        'attach_name' => '',
    ];

    /**
     * 初始化
     *
     * @param array $options 参数
     * @return Email
     */
    public static function instance($options = [])
    {
        if (is_null(self::$instance)) {
            self::$instance = new static($options);
        }

        return self::$instance;
    }

    /**
     * 构造函数
     * @param array $options
     */
    public function __construct($options = [])
    {
        $config = config('option.mail');
        if ($config) {
            $this->options = array_merge($this->options, $config);
        }
        $this->options = array_merge($this->options, $options);

        switch ($this->options['mail_type']) {
            case 1:
                require_once(root_path() . 'vendor/swiftmailer/swiftmailer/lib/swift_required.php');

                // 创建Transport对象，设置邮件服务器和端口号，并设置用户名和密码以供验证
                $transport = new \Swift_SmtpTransport($this->options['host'], $this->options['port'], $this->options['encryption']);
                $transport->setUsername($this->options['username'])->setPassword($this->options['password']);

                // 创建mailer对象
                //$mailer = \Swift_Mailer::newInstance($transport);
                $mailer = new \Swift_Mailer($transport);
                $this->mail = $mailer;
                break;
            case 2:
                //$dsn = 'smtp://localhost';
                $user = $this->options['username'];
                $pass = $this->options['password'];
                $server = $this->options['host'];
                $port = $this->options['port'];
                $dsn = 'smtp://' . $user . ':' . $pass . '@' . $server . ':' . $port;
                $transport = Transport::fromDsn($dsn);
                $mailer = new Mailer($transport);
                $this->mail = $mailer;
                break;
            default: break;
        }
    }

    /**
     * 设置邮件主题
     * @param string $subject
     * @return $this
     */
    public function subject($subject)
    {
        $this->options['subject'] = $subject;
        return $this;
    }

    /**
     * 设置发件人
     * @param string $email
     * @param string $name
     * @return $this
     */
    public function from($email, $name = '')
    {
        $this->options['from'] = $email;
        $this->options['from_name'] = $name;
        return $this;
    }

    /**
     * 设置收件人
     * @param string $email
     * @param string $name
     * @return $this
     */
    public function to($email, $name = '')
    {
        $this->options['to'] = $email;
        $this->options['to_name'] = $name;
        return $this;
    }

    /**
     * 设置抄送人
     * @param string $email
     * @param string $name
     * @return $this
     */
    public function cc($email, $name = '')
    {
        $this->options['cc'] = $email;
        $this->options['cc_name'] = $name;
        return $this;
    }

    /**
     * 设置密送人
     * @param string $email
     * @param string $name
     * @return $this
     */
    public function bcc($email, $name = '')
    {
        $this->options['bcc'] = $email;
        $this->options['bcc_name'] = $name;
        return $this;
    }

    /**
     * 设置邮件正文
     * @param string $body
     * @param boolean $ishtml
     * @return $this
     */
    public function message($body, $ishtml = true)
    {
        $this->options['body'] = $body;
        $this->options['ishtml'] = $ishtml;
        return $this;
    }

    /**
     * 添加附件
     * @param string $path 附件路径
     * @param string $name 附件名称
     * @return $this
     */
    public function attachment($path, $name = '')
    {
        $this->options['attach_path'] = $path;
        $this->options['attach_name'] = $name;
        return $this;
    }

    /**
     * 获取最后产生的错误
     * @return string
     */
    public function getError()
    {
        return $this->_error;
    }

    /**
     * 设置错误
     * @param string $error 信息信息
     */
    protected function setError($error)
    {
        $this->_error = $error;
    }

    /**
     * 发送邮件
     * @return boolean
     */
    public function send()
    {
        $result = false;
        switch ($this->options['mail_type']) {
            case 0:
                // 使用mail方法发送邮件
                $headers = 'MIME-Version: 1.0' . "\r\n";
                $headers .= "Content-type: text/html; charset=" . $this->options['charset'] . "\r\n";
                $headers .= "To: {$this->options['to_name']} <{$this->options['to']}>\r\n"; //收件人
                $headers .= "From: {$this->options['from_name']} <{$this->options['from']}>\r\n"; //发件人
                $result = mail($this->options['to'], $this->options['subject'], $this->options['body'], $headers);
                $this->setError($result ? '' : error_get_last()['message']);
                break;
            case 1:
                // 使用swiftmailer发送
                // 创建message对象
                $message = (new \Swift_Message())
                    ->setFrom($this->options['from'], $this->options['from_name'])
                    ->setTo([$this->options['to'] => $this->options['to_name']])
                    ->setSubject($this->options['subject'])
                    ->setContentType($this->options['content_type'])
                    ->setBody($this->options['body']);

                if ($this->options['cc'] && $this->options['cc_name']) {
                    // 添加抄送人
                    $message->setCc([$this->options['cc'] => $this->options['cc_name']]);
                }
                if ($this->options['bcc'] && $this->options['bcc_name']) {
                    // 添加密送人
                    $message->setBcc([$this->options['bcc'] => $this->options['bcc_name']]);
                }
                if ($this->options['attach_path'] && $this->options['attach_name']) {
                    // 创建attachment对象，content-type这个参数可以省略
                    //$attachment = \Swift_Attachment::fromPath('image.jpg', 'image/jpeg')->setFilename('cool.jpg');
                    $attachment = \Swift_Attachment::fromPath($this->options['attach_path'])->setFilename($this->options['attach_name']);
                    // 添加附件
                    $message->attach($attachment);
                }

                // 设置邮件回执
                //$message->setReadReceiptTo('receipt@163.com');

                try {
                    $result = $this->mail->send($message);
                } catch (Exception $e) {
                    $this->setError($e->getMessage());
                }

                $this->setError($result ? '' : $this->_error);
                break;
            case 2:
                // 使用 symfony mailer 发送
                $email = (new Email())
                    ->from(new Address($this->options['from'],  $this->options['from_name']))
                    ->to($this->options['to'])
                    ->subject($this->options['subject'])
                    ->text('Sending emails is fun again!')
                    ->html($this->options['body']);

                if ($this->options['cc'] && $this->options['cc_name']) {
                    // 添加抄送人
                    $email->cc($this->options['cc']);
                }
                if ($this->options['bcc'] && $this->options['bcc_name']) {
                    // 添加密送人
                    $email->bcc($this->options['bcc']);
                }
                if ($this->options['attach_path'] && $this->options['attach_name']) {
                    //$attachment = ::fromPath($this->options['attach_path'])->setFilename($this->options['attach_name']);
                    // 添加附件
                    //$email->attach($attachment);
                }

                try {
                    $result = $this->mail->send($email);
                } catch (Exception $e) {
                    $this->setError($e->getMessage());
                }

                $this->setError($result ? '' : $this->_error);
                break;
            default:
                // 邮件功能已关闭
                $this->setError(__('Mail already closed'));
                break;
        }
        //return $result;
        return [
            'status' => $result,
            'msg' => $this->_error
        ];
    }
}
